﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System_States_Signals;
using System.Threading;

namespace Abs_classes_data
{
    public abstract class abs_controller
    {
        abs_controlled_object _object;
        public abs_controlled_object Object
        {
            get { return _object; }
        }

        /// <summary>
        /// Отображает текущее состояние контроллера
        /// Используется для остановки потока проверки датчика
        /// </summary>
        private Controller_State _state = Controller_State.Not_started;
        public Controller_State State
        {
            get { return _state; }
            set { _state = value; }
        }

        /// <summary>
        /// Датчик, за который отвечает контроллер
        /// </summary>
        protected abs_sensor _sensor;

        /// <summary>
        /// Нормальное значение параметра
        /// </summary>
        protected Double _normal_value;

        /// <summary>
        /// Конструктор абстрактного контроллера
        /// </summary>
        /// <param name="normal_value">нормальное значение параметра, к-рый будет контролироваться</param>
        public abs_controller(abs_controlled_object obj, Double normal_value)
        {
            if (null != obj)
            {
                _object = obj;
                _normal_value = normal_value;
                Console.WriteLine("Запуск контроллера");                
                Create_Sensor(obj);
            }
        }
        
        protected abstract void Create_Sensor(abs_controlled_object obj);

        public virtual Double Data
        {
            get
            {
                return _sensor.Value;
            }
        }

        /// <summary>
        /// Контроль датчика
        /// Надо вынести в отдельный поток
        /// </summary>
        /// <returns>Состояние системы</returns>
        public abstract System_States_Signals.Value_State Check_statement();

        public abstract void Do_Work(Double value);

        /// <summary>
        /// Этот метод делает
        /// </summary>
        public abstract void Do_Crash();

        private void Crash_check()
        {
            while (Controller_State.Working == this._state)
            {
                lock (_sensor)
                {
                    if (Value_State.Crash == Check_statement())
                    {
                        CrashEventArgs args = new CrashEventArgs(_sensor.Value, this._normal_value);
                        OnCrash(this, args);
                        this._state = Controller_State.Stopped;
                    }
                }
                Thread.Sleep(500);
            }
        }

        public void StartChecking()
        {
            _state = Controller_State.Working;
            Thread _crash_control_thread = new Thread(Crash_check);
            _crash_control_thread.Start();
        }

        public delegate void CrashEventHandler(object abs_controller, CrashEventArgs crash_args);
        public event CrashEventHandler OnCrash;
    }
}